package com.yangyang.rpc.core.netcom.netty.server;

import com.yangyang.rpc.core.netcom.common.bean.RpcRequest;
import com.yangyang.rpc.core.netcom.common.bean.RpcResponse;
import com.yangyang.rpc.core.netcom.common.server.AbstractServer;
import com.yangyang.rpc.core.netcom.netty.codec.NettyDecoder;
import com.yangyang.rpc.core.netcom.netty.codec.NettyEncoder;
import com.yangyang.rpc.core.serialize.Serializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Created by chenshunyang on 2016/11/19.
 */
public class NettyServer extends AbstractServer{

    private Thread thread;

    @Override
    public void start(int port, Serializer serializer) throws Exception {

        thread = new Thread(new Runnable() {
            @Override
            public void run() {

                EventLoopGroup bossGroup = new NioEventLoopGroup();
                EventLoopGroup workerGroup = new NioEventLoopGroup();
                try {
                    ServerBootstrap bootstrap = new ServerBootstrap();
                    bootstrap.group(bossGroup, workerGroup)
                            .channel(NioServerSocketChannel.class)
                            .childHandler(new ChannelInitializer<SocketChannel>() {

                                @Override
                                protected void initChannel(SocketChannel channel) throws Exception {
                                    channel.pipeline()
                                            .addLast(new NettyDecoder(RpcRequest.class,serializer)) // 将 RPC 请求进行解码（为了处理请求）
                                            .addLast(new NettyEncoder(RpcResponse.class,serializer)) // 将 RPC 响应进行编码（为了返回响应）
                                            .addLast(new NettyServerHandler()); // 处理 RPC 请求
                                }

                            })
                            .option(ChannelOption.SO_TIMEOUT, 100)
                            .option(ChannelOption.SO_BACKLOG, 128)
                            .option(ChannelOption.TCP_NODELAY, true)
                            .option(ChannelOption.SO_REUSEADDR, true)
                            .childOption(ChannelOption.SO_KEEPALIVE, true);
                    ChannelFuture future = bootstrap.bind(port).sync();
                    logger.info(">>>>>>>>>>> yy-rpc server start success, netcon={}, port={}", NettyServer.class.getName(), port);
                    future.channel().closeFuture().sync();
                } catch (InterruptedException e) {
                    logger.error("", e);
                } finally {
                    workerGroup.shutdownGracefully();
                    bossGroup.shutdownGracefully();
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
        thread.join();
    }

    @Override
    public void destroy() throws Exception {
        thread.interrupt();
        logger.info(">>>>>>>>>>> yy-rpc server destroy success, netcon={}", NettyServer.class.getName());
    }
}
